<?php

// 'user' table management: all users (any status)
class User extends Model
{
	var $id = null;
    var $email = '';
    var $password = '';
    var $name = '';
    var $firstname = '';
    var $created_at = '';
    var $updated_at = '';
	var $status_id = null;
	var $active = 1;
	var $last_used_ip = '';

	function User()
	{
		parent::Model();
	}


	function get_by_id($id)
	{
		$this->db->select('u.id, u.email, u.password, u.firstname, u.name, u.created_at, u.updated_at, u.status_id, u.connection_count, u.last_connection, u.last_used_ip, s.code as status_code, s.label as status_label')
		         ->from('user u')
		         ->join('user_status s', 's.id = u.status_id')
		         ->where('u.id', $id)
		         ->where('u.active', 1)
		         ->limit(1);
		$query = $this->db->get();
		return $query->row();
	}


	function get_by_email($email)
	{
		$this->db->select('u.id, u.email, u.password, u.firstname, u.name, u.created_at, u.updated_at, u.status_id, u.connection_count, u.last_connection, s.code as status_code, s.label as status_label')
		         ->from('user u')
		         ->join('user_status s', 's.id = u.status_id')
		         ->where('u.email', $email)
		         ->where('u.active', 1)
		         ->limit(1);
		$query = $this->db->get();
		return $query->row();
	}


	function plain_get($id)
	{
		$this->db->select('id, email, password, firstname, name, created_at, updated_at, status_id, connection_count, last_connection')
		         ->from('user')
		         ->where('id', $id)
		         ->where('active', 1);
		$query = $this->db->get();
		return $query->row();
	}


	function all($filter = null)
	{
		$this->db->select('u.id, u.email, u.password, u.firstname, u.name, u.created_at, u.updated_at, u.status_id, s.code as status_code, s.label as status_label')
		         ->from('user u')
		         ->join('user_status s', 's.id = u.status_id')
		         ->where('active', 1);
		if ($filter) {
			$this->db->where($filter);
		}
		$query = $this->db->get();
		return $query->result();
	}

	function former_students($year = null)
	{
		$this->db->select('u.id, u.email, u.password, u.firstname, u.name, u.created_at, u.updated_at, u.status_id, s.code as status_code, s.label as status_label, e.value_int as promo_year')
		         ->from('user u')
		         ->join('user_status s', 's.id = u.status_id')
		         ->join('insc_entry e', 'u.id = e.user_id')
		         ->join('insc_field f', 'e.field_id = f.id')
		         ->where('active', 1)
		         ->where('s.code = "former_student"')
		         ->where('f.field_id = "promotion"');
		if ($year) {
			$this->db->where('e.value_int', intval($year));
		}
		$query = $this->db->get();
		return $query->result();
	}


	function update(&$user, &$data)
	{
		// set
		if (isset($data['firstname'])) $user->firstname = clean_str($data['firstname']);
		if (isset($data['name']))      $user->name = clean_str($data['name']);
		if (isset($data['email']))     $user->email = clean_str($data['email']);

		$password_confirm = true;
		if (isset($data['password']) && !empty($data['password'])) {
			$user->password = crypt_password($data['password']);
			if (isset($data['password_confirm']) && !empty($data['password_confirm'])) {
				$password_confirm = $user->password == crypt_password($data['password_confirm']);
			}
			else {
				$password_confirm = false;
			}
		}

		// check
		$errors = array();
		if (!$user->firstname)          $errors[] = 'Le prénom ne peut pas être vide';
		if (!$user->name)               $errors[] = 'Le nom ne peut pas être vide';
		if (!check_email($user->email)) $errors[] = "L'adresse e-mail n'est pas valide";
		if (!$this->has_unique_email($user)) $errors[] = 'Cette adresse e-mail est déjà enregistrée';
		if (!$user->password)           $errors[] = 'Le mot de passe doit être renseigné';
		if (!$password_confirm)         $errors[] = 'Le mot de passe et la confirmation du mot de passe ne correspondent pas';

		return $errors;
	}

	function update_password(&$user, &$data)
	{
		$errors = array();
		$current_password = crypt_password($data['current_password']);
		if ($current_password != $user->password) {
			$errors[] = "Le mot de passe actuel n'est pas bon";
		}
		if (empty($data['password'])) {
			$errors[] = "Le nouveau mot de passe doit être renseigné";
		}
		else {
			$user->password = crypt_password($data['password']);
		}
		if ($user->password != crypt_password($data['password_confirm'])) {
			$errors[] = "La confirmation du nouveau mot de passe ne correspond pas";
		}
		return $errors;
	}

	/**
	 * Sauvegarde le user passé en paramètre en base de données
	 * @return true si l'ajout/update s'est bien passé(e), false sinon
	 */
	function save($user)
	{
		$result = null;
		if ($user->id == null) {
			$result = $this->db->insert('user', $user);
			$user->id = $this->db->insert_id();
		}
		else {
			$this->db->where('id', $user->id);
			$result = $this->db->update('user', $user);
		}
		return $result;
	}

	function delete($id)
	{
		return $this->db->update('user', array('active' => 0), 'id = '.intval($id));
	}

	function restore($id)
	{
		return $this->db-update('user', array('active' => 1), 'id = '.intval($id));
	}

	// non generic -------------------------------------------------------------

	function connect()
	{
		if (!$this->email || !$this->password) {
			return FALSE;
		}

		$this->db->select('u.id, u.email, u.password, u.name, u.firstname, u.status_id, s.code as status_code')
				 ->from('user u')
				 ->join('user_status s', 's.id = u.status_id')
				 ->where('u.email', $this->email)
				 ->where('u.password', $this->password)
				 ->where('u.active', 1)
				 ->limit(1);
		$user = $this->db->get()->row();
		if ($user) {
			$sql = 'UPDATE user
					SET connection_count = connection_count + 1,
					    last_connection = NOW(),
					    last_used_ip = "'.$this->last_used_ip.'"
					WHERE id = '.$user->id.';';
			$this->db->query($sql);
			return $user;
		}
		return false;
	}

	/**
	 * Assigner un statut
	 * @param status_id : valeur du champ user_status.id
	 * @param creator_id : id de l'user opérant le changement
	 * @param bypass_history : si true, le nouveau statut ne sera pas archivé dans l'historique
	 * @return status_id affecté, ou 0 si statut invalide
	 */
	function set_status(&$user, $status_id, $creator_id = null, $bypass_history = false)
	{
		$status_id = intval($status_id);
		// if no creator is provided, we assume the status is edited by the user himself
		$creator_id = intval($creator_id == null ? $user->id : $creator_id);
		if ($status_id != 0) {
			$user->status_id = $status_id;
		 	if (!$bypass_history) {
			// archivage du nouveau statut
				$sql = 'INSERT INTO user_status_history(user_id, status_id, created_at, creator_id)
					    VALUES ('.$user->id.', '.$status_id.', NOW(), '.$creator_id.');';
				$this->db->query($sql);
			}
		}
		return $status_id;
	}

	/**
	 * Assigner un statut depuis un status_code
	 * @param status_code : valeur du champ user_status.code
	 * @param creator_id : id de l'user opérant le changement
	 * @param bypass_history : si true, le nouveau statut ne sera pas archivé dans l'historique
	 * @return status_id affecté, ou 0 si code statut inexistant
	 */
	function set_status_from_code(&$user, $status_code, $creator_id = null, $bypass_history = false)
	{
		$this->db->select('id')
		         ->from('user_status')
				 ->where('code', $status_code);
		$res = $this->db->get()->row();
		$status_id = $res ? $res->id : 0;
		return $this->set_status($user, $status_id, $creator_id, $bypass_history);
	}

	function get_status_history($user_id)
	{
		$this->db->select('h.id, h.user_id, h.status_id, h.created_at, h.creator_id, s.code AS status_code, s.label AS status_label, u.name AS creator_name, u.firstname AS creator_firstname')
		         ->from('user_status_history h')
		         ->join('user_status s', 's.id = h.status_id')
		         ->join('user u', 'u.id = h.creator_id')
		         ->where('h.user_id', $user_id)
		         ->order_by('h.created_at');
		$query = $this->db->get();
		return $query->result();
	}

	function get_status_id($user_id)
	{
		$query = $this->db->get_where('user', array('id' => $user_id), 1);
		$result = $query->row();
		return intval($result->status_id);
	}

	function save_status_id(&$user)
	{
		return $this->db->update('user', array('status_id' => $user->status_id), array('id' => $user->id));
	}

	function has_unique_email(&$user)
	{
		$this->db->select('id')
		         ->from('user')
				 ->where('email', $user->email)
				 ->where('id != '.intval($user->id));
		return !$this->db->get()->row();
	}

	/**
	 * Sauvegarder un ensemble de champs d'inscription pour un utilisateur
	 * @return l'array des erreurs collectées (vide si pas d'erreurs)
	 */
	function insc_field_submission($field_set)
	{
		// Liste pour logger les erreurs
		$errors = array();

		// On vérifie que le user courant a un id, sinon on ne peut rien faire
		if($this->id == null) {
			$errors[] = 'Le candidat n\'est pas sauvegardé';
			return $errors;
		}

		// On vérifie que c'est un 'candidat in progress'
		$this->load->model('UserStatus');
		if($this->status_id !== $this->UserStatus->get_id_by_code('candidat_complete')) {
			$errors[] = 'Le candidat n\'est pas en demande d\'inscription';
			return $errors;
		}

		// Modèle permettant de manipuler les champs d'inscription
		$this->load->model('Insc');
		$field_ar = new Insc();

		$now = date_db_format();

		foreach($field_set as $field_id => $field_value) {
			$field_ar->field_id = $field_id;
			if($field_ar->insc_field_exists()) {
				$field = $field_ar->insc_field_getinfos();
				$filled_row = array(
					'field_id' => $field->id,
					'user_id' => $this->id,
					'value_'.$field->field_type => $field_value,
					'created_at' => $now,
					'updated_at' => $now
				);
				$field_ar->insc_entry_add($filled_row);
			}
			else
				$errors[] = 'Le champ « '.$field_id.' » n\'existe pas';
		}

		return $errors;
	}
}
